package com.ndp.fb.mq.service.schedulerservice.business;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSONObject;
import com.esotericsoftware.minlog.Log;
import com.ndp.fb.constant.CommonConstants;
import com.ndp.fb.enums.customaudience.CustomAudienceDataSourceSubType;
import com.ndp.fb.exception.ErrorCode;
import com.ndp.fb.exception.ResourceMsgManager;
import com.ndp.fb.model.CustomAudienceTemplateRoster;
import com.ndp.fb.model.fbagent.param.APIPriority;
import com.ndp.fb.model.fbagent.param.ApiCallBackTarget;
import com.ndp.fb.model.fbagent.param.customaudience.CustomAudienceParam;
import com.ndp.fb.model.fbagent.param.customaudience.CustomAudienceUserParam;
import com.ndp.fb.model.fbagent.param.entrustaccount.EntrustAccountParam;
import com.ndp.fb.model.fbagent.result.FBSuccess;
import com.ndp.fb.model.fbagent.result.common.FBSingleId;
import com.ndp.fb.model.fbagent.result.customaudiences.FbCustomaudiencesSimple;
import com.ndp.fb.mongo.api.CustomAudienceTemplateMongoService;
import com.ndp.fb.fbagent.service.CustomaudiencesFbServices;

import com.ndp.fb.mq.api.service.schedulerservice.AdAccountsSchedulerService;
import com.ndp.fb.mq.utils.ReadMongoNullException;
import com.ndp.fb.rdb.api.CustomAudienceRdbService;
import com.ndp.fb.rdb.api.CustomAudienceTemplateRdbService;
import com.ndp.fb.rdb.api.EntrustAccountRdbService;
import com.ndp.fb.rdb.api.FbUserPermissionRdbService;
import com.ndp.fb.rdb.api.UserRdbServices;
import com.ndp.fb.rdb.model.AdaccountPermissionExt;
import com.ndp.fb.rdb.model.EntrustAccount;
import com.ndp.fb.rdb.model.User;
import com.ndp.fb.rdb.model.customaudience.*;
import com.ndp.fb.redis.api.RedisClient;
import com.ndp.fb.redis.api.RedisDistributedLockService;
import com.ndp.fb.util.ListUtil;
import com.ndp.fb.util.StringUtil;
import com.restfb.DefaultJsonMapper;
import com.restfb.JsonMapper;
import com.restfb.json.JsonArray;
import com.restfb.json.JsonException;
import com.restfb.json.JsonObject;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.TimeUnit;

import com.ndp.fb.util.UUID;

/**
 * 定时从facebook 查询账号对应的 自定义受众的数据用List Map的方式存储到Redis里面
 * 便于前台可快速获取每个账号下的 自定义受众数据
 * <p>
 * Created by hunk.qin on 2015/3/10.
 */
@Component
public class FetchCustomaudiencesService {

    private static Logger logger = LoggerFactory.getLogger(FetchCustomaudiencesService.class);

    private static final String ACCOUNT_AUDIENCE_NOT_ACCEPTED = "The corporate terms of service has not been accepted";

    private JsonMapper jsonMapper = new DefaultJsonMapper();

    @Autowired
    private RedisClient redisClient;

    @Autowired
    AdAccountsSchedulerService adaccountsSchedulerService;

    @Reference
    private CustomaudiencesFbServices customaudiencesFbServices;

    @Reference
    private CustomAudienceTemplateMongoService customAudienceMongoService;

    @Reference
    private CustomAudienceRdbService customAudienceRdbService;

    @Reference
    private EntrustAccountRdbService entrustAccountRdbService;

    @Reference
    private CustomAudienceTemplateRdbService customAudienceTemplateRdbService;

    @Reference
    private FbUserPermissionRdbService fbUserPermissionRdbService;

    @Autowired
    RedisDistributedLockService redisDistributedLockService;

    @Reference
    UserRdbServices userRdbServices;

    /**
     * 新加账号
     *
     * @param accountId
     * @param templateId
     */
    public void addCustomaudiences(Long accountId, Long templateId) {
        logger.info("开始同步账号{},模版{}下自定义受众", accountId, templateId);
        CustomAudienceTemplate customAudienceTemplate = customAudienceTemplateRdbService.findById(templateId.toString());
        saveCustomAudienceItem(accountId, customAudienceTemplate);
    }

    /**
     * 新增账号，保存自定义受众并发送fb
     *
     * @param accountId
     * @param customAudienceTemplate
     */
    private void saveCustomAudienceItem(Long accountId, CustomAudienceTemplate customAudienceTemplate) {
        if (customAudienceTemplate == null) {
            return;
        }
        String key = CommonConstants.SYNC_CUSTOM_AUDIENCE + "-" + accountId + "-" + customAudienceTemplate.getId();
        try {
            if (redisDistributedLockService.tryLock(key, 1, TimeUnit.MINUTES)) {
                List<CustomAudienceItem> byTemplateIdAndAccountId = customAudienceRdbService.findByTemplateIdAndAccountId(customAudienceTemplate.getId(), accountId);
                if (customAudienceTemplate != null && ListUtil.isEmpty(byTemplateIdAndAccountId)) {
                    //这个账号对应的模板之前没有保存
                    logger.info("同步自定义受众  tmpId" + customAudienceTemplate.getId() + " ;accountId>>>" + accountId);
                    //创建自定义受众
                    CustomAudienceItem customAudience = new CustomAudienceItem();
                    customAudience.setCustomAudienceId(-1l);
                    customAudience.setRequestQueueStatus(0);
                    customAudience.setDeliveryStatusCode(-1);
                    customAudience.setOperationStatusCode(-1);
                    customAudience.setFbAccountId(accountId);
                    customAudience.setCustomAudienceTemplateId(customAudienceTemplate.getId());
                    customAudience.setDeliveryStatusDescription("");
                    customAudience.setTimeCreated(System.currentTimeMillis());
                    customAudience.setTimeUpdated(System.currentTimeMillis());
                    customAudience.setOperationStatusDescription("");
                    customAudience.setVersion("0");
                    Long aLong = customAudienceRdbService.saveCustomAudience(customAudience);
                    sendCustomAudienceToFB(customAudienceTemplate, accountId, aLong);
                }
            }
        } catch (Exception ex) {
            Log.error("保存自定义受众项失败", ex);
        } finally {
            redisDistributedLockService.unLock(key);
        }
    }

    /**
     * 新增账号同步自定义受众
     *
     * @param accountId
     */
    public void uploadCustomaudiencesByAccountId(Long accountId, String userId) {

        logger.info("开始同步用户{}+账号{}下 修改账号同步自定义受众", accountId, userId);

        List<AdaccountPermissionExt> adaccountHasPermissionExts = fbUserPermissionRdbService.getUserpermissionExts(accountId, userId);
        if (adaccountHasPermissionExts == null || adaccountHasPermissionExts.size() == 0) {

            logger.info("账号解绑删除自定义用户>>,不做处理由sql查询时来处理" + accountId);

        } else {

            logger.info("同步自定义受众>>>>>" + accountId);

            //查询拥有该账号权限的应用ID对应的自定义受众模板
            List<CustomAudienceTemplate> customAudienceTemplateList = customAudienceTemplateRdbService.findCustomAudienceTemplateByAccountId(accountId);

            //将每个模板都关联到账号上
            customAudienceTemplateList.forEach(item->{
                List<CustomAudienceItem> byTemplateIdAndAccountId = customAudienceRdbService.findByTemplateIdAndAccountId(item.getId(), accountId);
                //这个账号对应的模板之前没有保存
                if (ListUtil.isEmpty(byTemplateIdAndAccountId)) {
                    saveCustomAudienceItem(accountId, item);
                }
            });

        }

    }

    private void sendCustomAudienceToFB(CustomAudienceTemplate customAudienceTemplate, Long fbAccountId, Long id) {
        String token = adaccountsSchedulerService.getAdaccountsToken(fbAccountId);
        CustomAudienceParam param = new CustomAudienceParam();
        param.setAccessToken(token);
        param.setFbAccountId(fbAccountId);
        param.setName(customAudienceTemplate.getName());
        param.setDescription(customAudienceTemplate.getDescription());
        param.setSubtype(customAudienceTemplate.getSubtype());
        param.setResultClass(FBSingleId.class);
        param.setCallBack(true);
        param.setApiCallbackTargetType(ApiCallBackTarget.CustomAudience.AddCustomaudience.getTargetType());
        param.setApiPriorityCode(APIPriority.FetchCustomaudiences.getCode());

        List<CustomAudienceTemplateAndConnectionObject> customAudienceTemplateAndConnectionObjectList =
                customAudienceTemplateRdbService.getConnectionObjectIdByAudienceTemeplateId(customAudienceTemplate.getId());
        StringBuffer appIds = getAppIds(customAudienceTemplateAndConnectionObjectList);

        Map<String, String> equipment = new HashMap<>();
        equipment.put("id", String.valueOf(id));
        equipment.put("tmplid", String.valueOf(customAudienceTemplate.getId()));
        equipment.put("accountId", String.valueOf(fbAccountId));
        equipment.put("accesstoken", token);
        equipment.put("datasourcetype", customAudienceTemplate.getDataSourceType());
        equipment.put("appids", appIds.toString());
        equipment.put("datasourcesubtype", customAudienceTemplate.getDataSourceSubtype());
        equipment.put("fileimportedtype",customAudienceTemplate.getImportedType());
        equipment.put("name",customAudienceTemplate.getName());
        equipment.put("subtype",customAudienceTemplate.getSubtype());
        param.setEquipment(equipment);
        logger.info("send customaudience param to facebook.");
        logger.info("fileImportType:"+customAudienceTemplate.getImportedType());
        logger.info("name:"+customAudienceTemplate.getName());
        logger.info("subtype"+customAudienceTemplate.getSubtype());
        customaudiencesFbServices.createCustomAudience(param);
    }

    private StringBuffer getAppIds(List<CustomAudienceTemplateAndConnectionObject> customAudienceTemplateAndConnectionObjectList) {
        StringBuffer appIds = new StringBuffer();
        int i = 0;
        for (CustomAudienceTemplateAndConnectionObject customAudienceTemplateAndConnectionObject : customAudienceTemplateAndConnectionObjectList) {
            appIds.append(customAudienceTemplateAndConnectionObject.getConnectionObjectId());
            if (i <= customAudienceTemplateAndConnectionObjectList.size() - 1) {
                appIds.append(",");
            }
            i++;
        }
        return appIds;
    }


    /**
     * 发送到Facebook获取 Customaudiences
     */
    public void fetchCustomaudiences(Long accountId) {
        String token = adaccountsSchedulerService.getAdaccountsToken(accountId);
        if (StringUtil.isEmpty(token)) {
            logger.warn("fetchCustomaudiences token null:" + accountId);
            return;
        }
        customaudiencesFbServices.fetchCustomaudiencesForSimple(accountId, token, null, UUID.get());
    }


    /**
     * 获取facebook 返回值的回调
     */
    public void fetchCustomaudiencesCallBack(Map<String, String> equipment, Object object) {
        String accountId = equipment.get("accountId");
        String token = equipment.get("token");
        String fetchKey = equipment.get("fetchKey");

        logger.info("fetchCustomaudiencesCallBack accountId>>>>>>" + accountId);
        String json = object.toString();
        if (isEmptyObject(json)) return;
        if(!json.startsWith("{")) {
            logger.error("fetchCustomaudiencesCallBack 数据有问题：" + json);
            return;
        }
        try {
            List<FbCustomaudiencesSimple> fbCustomaudiencesSimpleAll = null;
            List<FbCustomaudiencesSimple> fbCustomaudiencesSimpleList = new ArrayList<>();
            JsonObject jsonObject = new JsonObject(json);
            Object jsonDataObject = jsonObject.get("data");
            JsonArray jsonArray = new JsonArray(jsonDataObject.toString());
            for (int i = 0; i < jsonArray.length(); i++) {
                fbCustomaudiencesSimpleList.add(jsonMapper.toJavaObject(jsonArray.get(i).toString(), FbCustomaudiencesSimple.class));
            }
            if (redisClient.hasKey(fetchKey)) {
                fbCustomaudiencesSimpleAll = (List<FbCustomaudiencesSimple>) redisClient.get(fetchKey);
                fbCustomaudiencesSimpleAll.addAll(fbCustomaudiencesSimpleList);
            } else {
                fbCustomaudiencesSimpleAll = fbCustomaudiencesSimpleList;
            }
            redisClient.set(fetchKey, fbCustomaudiencesSimpleAll, 1L, TimeUnit.HOURS.name());

            //如果有下一页
            if(jsonObject.has("paging")) {
                JsonObject pageJsonObject = jsonObject.getJsonObject("paging");
                if (pageJsonObject.has("next")) {
                    JsonObject after = pageJsonObject.getJsonObject("cursors");
                    customaudiencesFbServices.fetchCustomaudiencesForSimple(Long.valueOf(accountId), token, after.get("after").toString(), fetchKey);
                } else {
                    doFetchFinsh(accountId, token, fbCustomaudiencesSimpleAll);
                }
            } else {
                doFetchFinsh(accountId, token, fbCustomaudiencesSimpleAll);
            }

        } catch (JsonException e) {
            logger.error("fetchCustomaudiencesCallBack 解析出错：" + e);
            logger.error("fetchCustomaudiencesCallBack accountId>>>>>" + accountId + ";解析出错：" + json);
            return;
        }
    }

    /**
     * 全部完成时处理
     * @param accountId
     * @param token
     * @param fbCustomaudiencesSimpleAll
     */
    private void doFetchFinsh(String accountId, String token, List<FbCustomaudiencesSimple> fbCustomaudiencesSimpleAll) {
        //fb上成功自定义受众存库
        if (ListUtil.isEmpty(fbCustomaudiencesSimpleAll)) {
            logger.warn("获取账号：" + accountId + "下的自定义受众为空.");
            return ;
        }
        //set data to redis
        List<Map<String, String>> listmap = new ArrayList<>(fbCustomaudiencesSimpleAll.size());
        //批量更新名字
        //Map<Long, String> needUpdateNames = new HashMap<>();
        //我们库中此账号有的自定义受众  在facebook中没有了  需要更新已删除
       // List<Long> deleteItemIds = customAudienceRdbService.findByAccountId(Long.valueOf(accountId));

        for (FbCustomaudiencesSimple obj : fbCustomaudiencesSimpleAll) {
            //deleteItemIds.remove(obj.getId());

            //用于广告发布
            if (200 == obj.getDeliveryStatus().getCode() && 200 == obj.getOperationStatus().getCode()) {
                Map<String, String> fbCustomaudiencesMap = new HashMap<>();
                fbCustomaudiencesMap.put(CommonConstants.AUDIENCE_ID, String.valueOf(obj.getId()));
                fbCustomaudiencesMap.put(CommonConstants.AUDIENCE_NAME, obj.getName());
                fbCustomaudiencesMap.put(CommonConstants.AUDIENCE_SUBTYPE, obj.getSubtype());
                listmap.add(fbCustomaudiencesMap);
            }

//            /**
//             * 该受众在fb修改名字了 需要同步到我们库中
//             */
//            CustomAudienceItemWithName item = customAudienceRdbService.findByCustomAudienceId(obj.getId());
//            if (item == null)
//                continue;
////            if (!obj.getName().equals(item.getName())) {
////                needUpdateNames.put(item.getCustomAudienceTemplateId(), obj.getName());
////            }
//
//            CustomAudienceItem param = new CustomAudienceItem();
//            param.setCustomAudienceId(obj.getId());
//            //param.setApproximateCount(obj.getApproximateCount());
//            param.setTimeUpdated(obj.getTimeUpdated() * 1000);
//            param.setDeliveryStatusCode(obj.getDeliveryStatus().getCode());
//            param.setDeliveryStatusDescription(obj.getDeliveryStatus().getDescription());
//            param.setOperationStatusCode(obj.getOperationStatus().getCode());
//            param.setOperationStatusDescription(obj.getOperationStatus().getDescription());
//            customAudienceRdbService.updateByCustomAudienceId(param);
//            if (200 == obj.getDeliveryStatus().getCode() && 200 == obj.getOperationStatus().getCode()) {
//                syncLookalikeAudienceInCustomAudience(token, obj, item);
//                customAudienceTemplateRdbService.updateApproximateCount(item.getCustomAudienceTemplateId(), obj.getApproximateCount());
//            }
        }

        //不用删除 直接set
        redisClient.set(CommonConstants.AUDIENCE_REDIS_PREFIX + accountId, listmap);
//        if (!CollectionUtils.isEmpty(needUpdateNames)) {
//            List<CustomAudienceTmplSimple> customAudienceTmplSimples = new ArrayList<>();
//            CustomAudienceTmplSimple customAudienceTmplSimple;
//            for (Map.Entry<Long, String> entry : needUpdateNames.entrySet()) {
//                customAudienceTmplSimple = new CustomAudienceTmplSimple();
//                customAudienceTmplSimple.setId(entry.getKey());
//                customAudienceTmplSimple.setName(entry.getValue());
//                customAudienceTmplSimples.add(customAudienceTmplSimple);
//            }
//            customAudienceTemplateRdbService.batchUpdateName(customAudienceTmplSimples);
//        }
       //delFbAudienceNotInWe(deleteItemIds);
    }

    /**
     * 以自定义受众为基础同步到该账号下相似受众
     *
     * @param token
     * @param obj
     * @param item
     */
    private void syncLookalikeAudienceInCustomAudience(String token, FbCustomaudiencesSimple obj, CustomAudienceItemWithName item) {
        if (obj.getSubtype().equals("CUSTOM")) {
            //account 账号需要同步到相似受众
            //以当前的自定义受众模板ID为源模板ID,查询该源对应的相似受众模板.
            List<CustomAudienceTemplate> lookAliketemplateList = customAudienceTemplateRdbService.getCustomAudienceByOriginId(item.getCustomAudienceTemplateId());
            for (CustomAudienceTemplate lookAlikeAudienceTemplate : lookAliketemplateList) {
                //查询当前相似受众下是否有该账号
//                List<CustomAudienceItem> customAudienceItemList = customAudienceRdbService.findByTemplateIdAndAccountId(lookAlikeAudienceTemplate.getId(),param.getFbAccountId());
//                if(customAudienceItemList != null && customAudienceItemList.size() >0){
//                    CustomAudienceItem customAudienceItem = customAudienceItemList.get(0);
//                    //未发送给facebook前才创建,否则不重复创建
//                    if(customAudienceItem.getRequestQueueStatus() == 0 && lookAlikeAudienceTemplate.getOriginType()!= null
//                            && lookAlikeAudienceTemplate.getOriginType().equals("custom_audience")  ){
//                        logger.info("以自定义受众来创建相似受众");
//                        customaudiencesFbServices.createCustomAudienceLookalike(lookAlikeAudienceTemplate.getName(),lookAlikeAudienceTemplate.getCountryCode(),
//                                lookAlikeAudienceTemplate.getCustomRatio().toString(),customAudienceItem.getFbAccountId(),obj.getId(),customAudienceItem.getId(),token);
//                    }else if(lookAlikeAudienceTemplate.getOriginType()!= null && lookAlikeAudienceTemplate.getOriginType().equals("page")){
//                        logger.info("以page为基础来创建相似受众");
//                        customaudiencesFbServices.createCustomAudienceLookalikeByPage(lookAlikeAudienceTemplate.getOriginId(),lookAlikeAudienceTemplate.getCountryCode(),
//                                lookAlikeAudienceTemplate.getCustomRatio().toString(),lookAlikeAudienceTemplate.getName(),
//                                customAudienceItem.getFbAccountId(),token,customAudienceItem.getId());
//                    }
//                }
                Long fbAccountId = item.getFbAccountId();
                if (isNeedCreate(lookAlikeAudienceTemplate, fbAccountId)) {
                    Long tmplateId = lookAlikeAudienceTemplate.getId();
                    String key = CommonConstants.SYNC_CUSTOM_AUDIENCE + "-" + fbAccountId + "-" + tmplateId;
                    try {
                        if (redisDistributedLockService.tryLock(key, 1, TimeUnit.MINUTES)) {
                            CustomAudienceItem lookalikeCustomAudience = null;
                            List<CustomAudienceItem> byTemplateIdAndAccountId = customAudienceRdbService.findByTemplateIdAndAccountId(tmplateId, fbAccountId);
                            if (byTemplateIdAndAccountId == null || byTemplateIdAndAccountId.size() == 0) {
                                lookalikeCustomAudience = new CustomAudienceItem();
                                lookalikeCustomAudience.setCustomAudienceId(-1l);
                                lookalikeCustomAudience.setDeliveryStatusCode(-1);
                                lookalikeCustomAudience.setOperationStatusCode(-1);
                                lookalikeCustomAudience.setRequestQueueStatus(0);
                                lookalikeCustomAudience.setFbAccountId(item.getFbAccountId());
                                lookalikeCustomAudience.setCustomAudienceTemplateId(lookAlikeAudienceTemplate.getId());
                                lookalikeCustomAudience.setDeliveryStatusDescription("");
                                lookalikeCustomAudience.setTimeCreated(System.currentTimeMillis());
                                lookalikeCustomAudience.setTimeUpdated(System.currentTimeMillis());
                                lookalikeCustomAudience.setOperationStatusDescription("");
                                lookalikeCustomAudience.setVersion(System.currentTimeMillis() + "");
                                logger.info("以自定义受众来创建相似受众");
                                lookalikeCustomAudience.setOriginAudienceId(obj.getId());
                                Long customAudienceDbId = customAudienceRdbService.saveCustomAudience(lookalikeCustomAudience);
                                lookalikeCustomAudience.setId(customAudienceDbId);
                            } else {
                                lookalikeCustomAudience = byTemplateIdAndAccountId.get(0);
                            }
                            if (lookalikeCustomAudience.getRequestQueueStatus() != 1) {
                                customaudiencesFbServices.createCustomAudienceLookalike(lookAlikeAudienceTemplate.getName(), lookAlikeAudienceTemplate.getCountryCode(),
                                        lookAlikeAudienceTemplate.getCustomRatio().toString(), item.getFbAccountId(), obj.getId(), lookalikeCustomAudience.getId(), token);
                            }
                        }
                    } finally {
                        redisDistributedLockService.unLock(key);
                    }
                } else {
                    logger.error("已经被解绑，不能创建相似受众 fbaccount>>>" + fbAccountId);
                }
            }
        }
    }

    private boolean isNeedCreate(CustomAudienceTemplate lookAlikeAudienceTemplate, Long fbAccountId) {
        boolean isNeed = false;
        try {
            //获取模板创建者
            User user = userRdbServices.getUserByTicket(lookAlikeAudienceTemplate.getUserId());
            List<EntrustAccount> adAccountListByOrgId = entrustAccountRdbService.findAdAccountListByOrgId(user.getOrgId());
            Set<Long> hasP = new HashSet<>();
            for (EntrustAccount entrustAccount : adAccountListByOrgId) {
                hasP.add(entrustAccount.getFbAccountId());
            }
            isNeed = hasP.contains(fbAccountId);
        } catch (Exception e) {
           logger.error("infi>>>", e);
        }
        return isNeed;
    }

    private void delFbAudienceNotInWe(List<Long> items) {
        if (ListUtil.isEmpty(items))
            return;

        //找出需要删除的自定义受众
        List<CustomAudienceItem> deleteCustomAudienceItemList = new ArrayList<>();
        items.forEach(item -> {
            CustomAudienceItemWithName customAudienceItem = customAudienceRdbService.findByCustomAudienceId(item);
            if (customAudienceItem != null) {
                deleteCustomAudienceItemList.add(customAudienceItem);
            }
        });

        customAudienceRdbService.updateIsDelete(items, ResourceMsgManager.getResource("zh_CN","CUSTOM_AUDIENCE_DEL_REASON_BY_FACEBOOK"));

        /**
         * 如果自定义受众子项被删除,检查该模板下所有子项是否都删除，如果全删除所关联的模板也应该被删除
         */
        List<Long> templateIds = new ArrayList<>();
        if (ListUtil.isEmpty(deleteCustomAudienceItemList))
            return;
        deleteCustomAudienceItemList.forEach(item -> {
            int count = customAudienceTemplateRdbService.getCustomAudienceItemCountByTemplateId(item.getCustomAudienceTemplateId());
            if (count == 0) {
                //删除自定义受众模板
                templateIds.add(item.getCustomAudienceTemplateId());
            }
        });
        if (ListUtil.isEmpty(templateIds))
            return;
        customAudienceTemplateRdbService.delByIds(templateIds,ResourceMsgManager.getResource("zh_CN","CUSTOM_AUDIENCE_TEMPLATE_DEL_REASON_BY_FACEBOOK"));
    }


    protected boolean isEmptyObject(String json) {
        return "{}".equals(json);
    }

    /**
     * 账号同意自定义受众相关政策条款 callback
     */
    public void accountAgreeCallBack(Map<String, String> equipment, Object object) {
        logger.info("加受众策略0>>>>>>");
        if (object != null) {
            FBSuccess success;
            try {
                success = (FBSuccess) object;
            } catch (Exception e) {
                logger.error("账号同意自定义受众相关政策条款错误日志", object.toString());
                return;
            }
            if (success.isSuccess()) {
                Long accountId = Long.valueOf(equipment.get("accountId"));
                logger.info("加受众策略1>>>>>>"+equipment.get("accountId"));
                entrustAccountRdbService.updateAgreeCustomAudience(accountId);    //同意fb条款成功后更新 我们广告账号表
                String test = equipment.get("test");
                if ("1".equals(test)){
                    logger.info("加受众策略2异常>>>>>>"+equipment.get("accountId"));
                    return;
                }
                String accesstoken = equipment.get("accesstoken");
                String name = equipment.get("name");
                String description = equipment.get("description");
                String subtype = equipment.get("subtype");
                CustomAudienceParam param = new CustomAudienceParam();
                param.setAccessToken(accesstoken);
                param.setFbAccountId(accountId);
                param.setName(name);
                if (StringUtil.isNotEmpty(description))
                    param.setDescription(description);
                param.setSubtype(subtype);
                param.setResultClass(FBSingleId.class);
                param.setCallBack(true);
                param.setApiCallbackTargetType(ApiCallBackTarget.CustomAudience.AddCustomaudience.getTargetType());
                param.setApiPriorityCode(APIPriority.FetchCustomaudiences.getCode());
                //多余的三个参数不用携带了
                equipment.remove(name);
                equipment.remove(description);
                equipment.remove(subtype);
                param.setEquipment(equipment);
                customaudiencesFbServices.createCustomAudience(param);

            }
        }
    }

    /**
     * 添加自定义受众第一次 回调
     */
    public void addCustomaudiencesCallBack(Map<String, String> equipment, Object object) throws ReadMongoNullException {
        if (equipment == null || StringUtil.isEmpty(equipment.get("id")))
            logger.error("添加自定义受众回调参数空addCustomaudiencesCallBack");
        Long id = Long.valueOf(equipment.get("id"));
        Long tmplid = Long.valueOf(equipment.get("tmplid"));
        Long accountId = Long.valueOf(equipment.get("accountId"));
        String accesstoken = equipment.get("accesstoken");
        String datasourcesubtype = equipment.get("datasourcesubtype");
        String datasourcetype = equipment.get("datasourcetype");
        String fileimportedtype = equipment.get("fileimportedtype");
        String appids = equipment.get("appids");
        String name = equipment.get("name");
        String subType = equipment.get("subtype");
        logger.info("加受众1>>>>>>" + accountId);
        if (object instanceof FBSingleId) {
            Long fbCustomAudienceId = ((FBSingleId) object).getId();
            customAudienceRdbService.updateFbCustomAudienceId(id, fbCustomAudienceId);

            List<CustomAudienceTemplateRoster> customAudienceRosterList = customAudienceMongoService.getCustomAudienceTemplateRoster(tmplid);
            logger.info("加受众1个数查询出来条数>>>>>>" + customAudienceRosterList.size());
            if (ListUtil.isEmpty(customAudienceRosterList)) {
                logger.error("加受众没取到内容>>>>>>" + accountId + "---模板id是" + tmplid);
                //customAudienceRdbService.updateRequestQueueStatus(fbCustomAudienceId, 2);
                throw new ReadMongoNullException(ErrorCode.ERROR_60020);
            }
            logger.info("加受众1个数>>>>>>" + customAudienceRosterList.size());
            //创建空自定义受众成功，填充
            StringBuffer sb = new StringBuffer();
            String schema;
            boolean isUid = false;
            switch (CustomAudienceDataSourceSubType.getType(datasourcesubtype)) {
                case HASHES:
                    if ("phone".equals(fileimportedtype))
                        schema = "PHONE_SHA256";
                    else if ("email".equals(fileimportedtype))
                        schema = "EMAIL_SHA256";
                    else
                        schema = "";
                    break;
                case USER_IDS:
                    schema = "UID";
                    isUid = true;
                    break;
                case MOBILE_ADVERTISER_IDS:
                    schema = "MOBILE_ADVERTISER_ID";
                    break;
                default:
                    schema = "";
            }
            if (StringUtil.isEmpty(schema))
                return;
            sb.append("{\"schema\":\"" + schema + "\",\"data\":[");
            for (int i = 0; i < customAudienceRosterList.size(); i++) {
                if (CustomAudienceDataSourceSubType.HASHES.getType().equals(datasourcesubtype))
                    sb.append("\"").append(DigestUtils.sha256Hex(customAudienceRosterList.get(i).getValue())).append("\"");
                else if (CustomAudienceDataSourceSubType.MOBILE_ADVERTISER_IDS.getType().equals(datasourcesubtype))
                    sb.append("\"").append(customAudienceRosterList.get(i).getValue()).append("\"");
                else
                    sb.append(customAudienceRosterList.get(i).getValue());
                if (i < (customAudienceRosterList.size() - 1))
                    sb.append(",");
            }
            sb.append("]");
            if (isUid)
                sb.append(",\"app_ids\":[" + appids + "]");
            sb.append(",\"data_source\":{\"type\":\"" + datasourcetype + "\",\"sub_type\":\"" + datasourcesubtype + "\"}}");
            //UID, EMAIL_SHA256, PHONE_SHA256, or MOBILE_ADVERTISER_ID
            CustomAudienceUserParam customAudienceUserParam = new CustomAudienceUserParam();
            customAudienceUserParam.setFbAccountId(accountId);
            customAudienceUserParam.setAccessToken(accesstoken);
            customAudienceUserParam.setId(fbCustomAudienceId + "");
            customAudienceUserParam.setPayload(sb.toString());
            customAudienceUserParam.setCallBack(true);
            customAudienceUserParam.setApiCallbackTargetType(ApiCallBackTarget.CustomAudience.AddCustomaudienceSecond.getTargetType());
            customAudienceUserParam.setApiPriorityCode(APIPriority.FetchCustomaudiences.getCode());
            Map<String, String> equipmentSec = new HashMap<>();
            equipmentSec.put("fbCustomAudienceId", String.valueOf(fbCustomAudienceId));
            equipmentSec.put("accountId", String.valueOf(accountId));
            customAudienceUserParam.setEquipment(equipmentSec);
            customaudiencesFbServices.fillToCustomAudienceId(customAudienceUserParam);
        } else if(object.toString().indexOf(ACCOUNT_AUDIENCE_NOT_ACCEPTED) > -1) {
            //检测发现没同意，再次去同意fb条款再发
            acceptedFBTerms(equipment, accountId, accesstoken, name, subType);
        } else {
            String exception = object.toString();
            logger.error("自定义受众创建失败：" + exception);
        }
    }

    /**
     * 同意fb受众相关条款
     * @param equipment
     * @param accountId
     * @param accesstoken
     * @param name
     * @param subType
     */
    private void acceptedFBTerms(Map<String, String> equipment, Long accountId, String accesstoken, String name, String subType) {
        Map<String, String> agreeEquipment = new HashMap<>();
        agreeEquipment.put("accesstoken", accesstoken);
        EntrustAccountParam entrustAccountParam = new EntrustAccountParam();
        entrustAccountParam.setFbAccountId(accountId);
        entrustAccountParam.setRemoveAccountFromUrl(true);
        entrustAccountParam.setTosAccepted("{\"custom_audience_tos\":1}");
        entrustAccountParam.setAccessToken(accesstoken);
        entrustAccountParam.setCallBack(true);
        entrustAccountParam.setApiPriorityCode(APIPriority.GetEntrustAccounts.getCode());
        entrustAccountParam.setResultClassName(FBSuccess.class.getName());
        entrustAccountParam.setApiCallbackTargetType(ApiCallBackTarget.CustomAudience.AccountAgree.getTargetType());
        equipment.put("name", name);
        equipment.put("subtype", subType);
        entrustAccountParam.setEquipment(equipment);
        customaudiencesFbServices.agreeeCustomAudienceItem(entrustAccountParam);
    }

    /**
     * 添加自定义受众第二次 回调
     */
    public void addCustomaudiencesSecondCallBack(Map<String, String> equipment, Object object) {
        if (equipment == null || StringUtil.isEmpty(equipment.get("fbCustomAudienceId")))
            logger.error("添加自定义受众回调参数空addCustomaudiencesSecondCallBack");
        Long fbCustomAudienceId = Long.valueOf(equipment.get("fbCustomAudienceId"));
        logger.info("加受众2>>>>>>" + equipment.get("accountId"));
        //已请求
        customAudienceRdbService.updateRequestQueueStatus(fbCustomAudienceId, 1);
    }

    /**
     * 更新自定义受众 回调
     */
    public void updateCustomaudiencesCallBack(Map<String, String> equipment, Object object) {
        //TODO
        //String accountId=equipment.get("accountId");
        if (object instanceof FBSingleId) {
            Long id = ((FBSingleId) object).getId();
        } else {
            String exception = object.toString();
        }
    }

    /**
     * 创建自定义相似受众
     *
     * @param equipment
     * @param object
     */
    public void createCustomaudienceAlookLikeCallBack(Map<String, String> equipment, Object object) {
        logger.info("object:" + object);
        logger.info("equipment:" + equipment);
        String customAudienceDbId = equipment.get("customAudienceDbId");
        if (object instanceof FBSingleId) {
            Long fbCustomAudienceId = ((FBSingleId) object).getId();
            customAudienceRdbService.updateFbCustomAudienceIdAndStatus(Long.valueOf(customAudienceDbId), fbCustomAudienceId, 1);
        } else {
            logger.error(equipment + "" + object.toString());
            customAudienceRdbService.updateRequestQueueStatusById(Long.valueOf(customAudienceDbId), 1);
            try {
                JSONObject parse = JSONObject.parseObject(object.toString());
                String message = parse.getJSONObject("error").getString("message");
                customAudienceRdbService.updateDeliveryStatusDescriptionAndStatus(Long.valueOf(customAudienceDbId), 300, message);
            } catch (Exception e) {
                logger.error("", e);
            }
        }
    }

    public void UpdateCustomAudienceUsersCallBack(Map<String, String> equipment, Object message) throws ReadMongoNullException {
        JSONObject jsonObject = JSONObject.parseObject(message.toString());
        String customAudienceId = equipment.get("customAudienceId");
        String templateId = equipment.get("templateId");
        String customAudienceDbId = equipment.get("customAudienceDbId");
        String version = equipment.get("version");
        String token = equipment.get("accesstoken");
        if (jsonObject.containsKey("error")) {
            logger.info("object:" + message);
            logger.info("equipment:" + equipment);
            logger.error("更新受众fb返回错误>>>>>>---模板id是" + templateId);
            //customAudienceRdbService.updateRequestQueueStatus(customAudienceDbId, version, 2);
        } else {
            if (equipment != null) {
                customAudienceRdbService.updateRequestQueueStatus(customAudienceDbId, version, 1);
                if ("true".equalsIgnoreCase(equipment.get("next"))) {
                    equipment.remove("next");
                    String nextVersion = equipment.get("nextVersion");
                    equipment.put("version", nextVersion);
                    String dataSourceType = equipment.get("dataSourceType");
                    String dataSourceSubtype = equipment.get("dataSourceSubtype");
                    String fileType = equipment.get("fileType");
                    String appId = equipment.get("appId");
                    Long fbAccountId = Long.valueOf(equipment.get("fbAccountId"));
                    List<CustomAudienceTemplateRoster> customRosters = customAudienceMongoService.getCustomAudienceRosterHistory(Long.valueOf(templateId), nextVersion);
                    if (ListUtil.isEmpty(customRosters)) {
                        logger.error("更新受众没取到内容>>>>>>" + fbAccountId + "---模板id是" + templateId);
                        //customAudienceRdbService.updateRequestQueueStatus(customAudienceDbId, version, 2);
                        throw new ReadMongoNullException(ErrorCode.ERROR_60020);
                    }
                    String val = getCustomAudienceValString(dataSourceType, dataSourceSubtype, fileType, appId, customRosters);

                    String method = equipment.get("nextMethod");
                    CustomAudienceUserParam customAudienceParam = new CustomAudienceUserParam();
                    customAudienceParam.setMethod(method);

                    customAudienceParam.setEquipment(equipment);
                    customAudienceParam.setCallBack(true);
                    customAudienceParam.setApiCallbackTargetType(ApiCallBackTarget.CustomAudience.UpdateCustomAudienceUsers.getTargetType());
                    customAudienceParam.setApiPriorityCode(APIPriority.FetchCustomaudiences.getCode());
                    customAudienceParam.setId(customAudienceId);
                    customAudienceParam.setPayload(val);
                    customAudienceParam.setFbAccountId(fbAccountId);
                    customAudienceParam.setAccessToken(token);
                    customAudienceRdbService.updateRequestQueueStatus(customAudienceDbId, nextVersion, 0);
                    customaudiencesFbServices.updateCustomAudienceUsers(customAudienceParam);
                }
            }
        }

        logger.info("object:" + message);
        logger.info("equipment:" + equipment);
    }

    private String getCustomAudienceValString(String dataSourceType, String dataSourceSubtype, String fileType,
                                              String appId, List<CustomAudienceTemplateRoster> customRosters) {
        StringBuffer sb = new StringBuffer();
        String schema;
        boolean isUid = false;
        switch (CustomAudienceDataSourceSubType.getType(dataSourceSubtype)) {
            case HASHES:
                if ("PHONE".equalsIgnoreCase(fileType))
                    schema = "PHONE_SHA256";
                else if ("EMAIL".equalsIgnoreCase(fileType))
                    schema = "EMAIL_SHA256";
                else
                    schema = "";
                break;
            case USER_IDS:
                schema = "UID";
                isUid = true;
                break;
            case MOBILE_ADVERTISER_IDS:
                schema = "MOBILE_ADVERTISER_ID";
                break;
            default:
                schema = "";
        }
        if (StringUtil.isEmpty(schema))
            return null;
        sb.append("{\"schema\":\"" + schema + "\",\"data\":[");
        for (int i = 0, len = customRosters.size(); i < len; i++) {
            if (CustomAudienceDataSourceSubType.HASHES.getType().equals(dataSourceSubtype))
                sb.append("\"").append(DigestUtils.sha256Hex(customRosters.get(i).getValue())).append("\"");
            else if (CustomAudienceDataSourceSubType.MOBILE_ADVERTISER_IDS.getType().equals(dataSourceSubtype))
                sb.append("\"").append(customRosters.get(i).getValue()).append("\"");
            else
                sb.append(customRosters.get(i).getValue());
            if (i < (len - 1))
                sb.append(",");
        }
        sb.append("]");
        if (isUid) {
            sb.append(",\"app_ids\":[").append(appId).append("]");
        }
        sb.append(",\"data_source\":{\"type\":\"" + dataSourceType + "\",\"sub_type\":\"" + dataSourceSubtype + "\"}}");
        return sb.toString();
    }

    /**
     * 修改名称
     *
     * @param equipment
     * @param message
     */
    public void UpdateCustomaudienceNameCallBack(Map<String, String> equipment, Object message) {
        JSONObject jsonObject = JSONObject.parseObject(message.toString());
        if (jsonObject.containsKey("success") && jsonObject.getBoolean("success")) {
            String customAudienceDbId = equipment.get("customAudienceDbId");
            String version = equipment.get("version");
            customAudienceRdbService.updateRequestQueueStatus(customAudienceDbId, version, 1);
        }
    }
}
